﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.MissionViews.Sound.MusicBattleMissionView
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using psai.net;
using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.Core;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.MissionViews.Sound
{
  public class MusicBattleMissionView : MissionView, IMusicHandler
  {
    private const float ChargeOrderIntensityIncreaseCooldownInSeconds = 60f;
    private MusicBattleMissionView.BattleState _battleState;
    private MissionAgentSpawnLogic _missionAgentSpawnLogic;
    private int[] _startingTroopCounts;
    private float _startingBattleRatio;
    private bool _isSiegeBattle;
    private bool _isPaganBattle;
    private MissionTime _nextPossibleTimeToIncreaseIntensityForChargeOrder;

    bool IMusicHandler.IsPausable => false;

    private BattleSideEnum PlayerSide
    {
      get
      {
        Team playerTeam = Mission.Current.PlayerTeam;
        return playerTeam == null ? BattleSideEnum.None : __nonvirtual (playerTeam.Side);
      }
    }

    public MusicBattleMissionView(bool isSiegeBattle) => this._isSiegeBattle = isSiegeBattle;

    public override void OnBehaviorInitialize()
    {
      base.OnBehaviorInitialize();
      this._missionAgentSpawnLogic = Mission.Current.GetMissionBehavior<MissionAgentSpawnLogic>();
      MBMusicManager.Current.DeactivateCurrentMode();
      MBMusicManager.Current.ActivateBattleMode();
      MBMusicManager.Current.OnBattleMusicHandlerInit((IMusicHandler) this);
    }

    public override void OnMissionScreenFinalize()
    {
      MBMusicManager.Current.DeactivateBattleMode();
      MBMusicManager.Current.OnBattleMusicHandlerFinalize();
      this.Mission.PlayerTeam.PlayerOrderController.OnOrderIssued -= new OnOrderIssuedDelegate(this.PlayerOrderControllerOnOrderIssued);
    }

    public override void AfterStart()
    {
      this._nextPossibleTimeToIncreaseIntensityForChargeOrder = MissionTime.Now;
      this.Mission.PlayerTeam.PlayerOrderController.OnOrderIssued += new OnOrderIssuedDelegate(this.PlayerOrderControllerOnOrderIssued);
    }

    private void PlayerOrderControllerOnOrderIssued(
      OrderType orderType,
      IEnumerable<Formation> appliedFormations,
      OrderController orderController,
      object[] parameters)
    {
      if (orderType != OrderType.Charge && orderType != OrderType.ChargeWithTarget || !this._nextPossibleTimeToIncreaseIntensityForChargeOrder.IsPast)
        return;
      float currentIntensity = PsaiCore.Instance.GetCurrentIntensity();
      MBMusicManager.Current.ChangeCurrentThemeIntensity(currentIntensity * MusicParameters.PlayerChargeEffectMultiplierOnIntensity - currentIntensity);
      this._nextPossibleTimeToIncreaseIntensityForChargeOrder = MissionTime.Now + MissionTime.Seconds(60f);
    }

    private void CheckIntensityFall()
    {
      PsaiInfo psaiInfo = PsaiCore.Instance.GetPsaiInfo();
      if (psaiInfo.effectiveThemeId < 0)
        return;
      if (float.IsNaN(psaiInfo.currentIntensity))
      {
        MBMusicManager.Current.ChangeCurrentThemeIntensity(MusicParameters.MinIntensity);
      }
      else
      {
        if ((double) psaiInfo.currentIntensity >= (double) MusicParameters.MinIntensity)
          return;
        MBMusicManager.Current.ChangeCurrentThemeIntensity(MusicParameters.MinIntensity - psaiInfo.currentIntensity);
      }
    }

    public override void OnAgentRemoved(
      Agent affectedAgent,
      Agent affectorAgent,
      AgentState agentState,
      KillingBlow blow)
    {
      if (this._battleState == MusicBattleMissionView.BattleState.Starting)
        return;
      bool flag1 = affectedAgent.IsMine || affectedAgent.RiderAgent != null && affectedAgent.RiderAgent.IsMine;
      Team team = affectedAgent.Team;
      // ISSUE: explicit non-virtual call
      BattleSideEnum index = team != null ? __nonvirtual (team.Side) : BattleSideEnum.None;
      int num1;
      if (!flag1)
      {
        if (index != BattleSideEnum.None)
        {
          Team playerTeam = Mission.Current.PlayerTeam;
          // ISSUE: explicit non-virtual call
          num1 = (playerTeam != null ? __nonvirtual (playerTeam.Side) : BattleSideEnum.None) == index ? 1 : 0;
        }
        else
          num1 = 0;
      }
      else
        num1 = 1;
      bool flag2 = num1 != 0;
      if (!this._isSiegeBattle && affectedAgent.IsHuman && index != BattleSideEnum.None && this._battleState == MusicBattleMissionView.BattleState.Started && ((IEnumerable<int>) this._startingTroopCounts).Sum() >= MusicParameters.SmallBattleTreshold && MissionTime.Now.ToSeconds > (double) MusicParameters.BattleTurnsOneSideCooldown && this._missionAgentSpawnLogic.NumberOfRemainingTroops == 0)
      {
        int[] numArray = new int[2]
        {
          this._missionAgentSpawnLogic.NumberOfActiveDefenderTroops,
          this._missionAgentSpawnLogic.NumberOfActiveAttackerTroops
        };
        --numArray[(int) index];
        MusicTheme theme = MusicTheme.None;
        if (numArray[0] > 0 && numArray[1] > 0)
        {
          float num2 = (float) numArray[0] / (float) numArray[1];
          if ((double) num2 < (double) this._startingBattleRatio * (double) MusicParameters.BattleRatioTresholdOnIntensity)
            theme = MBMusicManager.Current.GetBattleTurnsOneSideTheme(this.Mission.MusicCulture.GetCultureCode(), this.PlayerSide != 0, this._isPaganBattle);
          else if ((double) num2 > (double) this._startingBattleRatio / (double) MusicParameters.BattleRatioTresholdOnIntensity)
            theme = MBMusicManager.Current.GetBattleTurnsOneSideTheme(this.Mission.MusicCulture.GetCultureCode(), this.PlayerSide == BattleSideEnum.Defender, this._isPaganBattle);
        }
        if (theme != MusicTheme.None)
        {
          MBMusicManager.Current.StartTheme(theme, PsaiCore.Instance.GetCurrentIntensity());
          this._battleState = MusicBattleMissionView.BattleState.TurnedOneSide;
        }
      }
      if (((!affectedAgent.IsHuman ? 0 : (affectedAgent.State != AgentState.Routed ? 1 : 0)) | (flag1 ? 1 : 0)) == 0)
        return;
      float deltaIntensity = flag2 ? MusicParameters.FriendlyTroopDeadEffectOnIntensity : MusicParameters.EnemyTroopDeadEffectOnIntensity;
      if (flag1)
        deltaIntensity *= MusicParameters.PlayerTroopDeadEffectMultiplierOnIntensity;
      MBMusicManager.Current.ChangeCurrentThemeIntensity(deltaIntensity);
    }

    private void CheckForStarting()
    {
      if (this._startingTroopCounts == null)
      {
        this._startingTroopCounts = new int[2]
        {
          this._missionAgentSpawnLogic.GetTotalNumberOfTroopsForSide(BattleSideEnum.Defender),
          this._missionAgentSpawnLogic.GetTotalNumberOfTroopsForSide(BattleSideEnum.Attacker)
        };
        this._startingBattleRatio = (float) this._startingTroopCounts[0] / (float) this._startingTroopCounts[1];
      }
      Agent main = Agent.Main;
      Vec2 vec2 = main != null ? main.Position.AsVec2 : Vec2.Invalid;
      Team playerTeam = Mission.Current.PlayerTeam;
      bool flag1 = playerTeam != null && playerTeam.FormationsIncludingEmpty.Any<Formation>((Func<Formation, bool>) (f => f.CountOfUnits > 0));
      float num1 = float.MaxValue;
      if (flag1 || vec2.IsValid)
      {
        foreach (Formation formation1 in (List<Formation>) Mission.Current.PlayerEnemyTeam.FormationsIncludingEmpty)
        {
          if (formation1.CountOfUnits > 0)
          {
            float num2 = float.MaxValue;
            if (!flag1 && vec2.IsValid)
              num2 = vec2.DistanceSquared(formation1.CurrentPosition);
            else if (flag1)
            {
              foreach (Formation formation2 in (List<Formation>) Mission.Current.PlayerTeam.FormationsIncludingEmpty)
              {
                if (formation2.CountOfUnits > 0)
                {
                  float num3 = formation2.CurrentPosition.DistanceSquared(formation1.CurrentPosition);
                  if ((double) num2 > (double) num3)
                    num2 = num3;
                }
              }
            }
            if ((double) num1 > (double) num2)
              num1 = num2;
          }
        }
      }
      int battleSize = ((IEnumerable<int>) this._startingTroopCounts).Sum();
      bool flag2 = false;
      if (battleSize < MusicParameters.SmallBattleTreshold)
      {
        if ((double) num1 < (double) MusicParameters.SmallBattleDistanceTreshold * (double) MusicParameters.SmallBattleDistanceTreshold)
          flag2 = true;
      }
      else if (battleSize < MusicParameters.MediumBattleTreshold)
      {
        if ((double) num1 < (double) MusicParameters.MediumBattleDistanceTreshold * (double) MusicParameters.MediumBattleDistanceTreshold)
          flag2 = true;
      }
      else if (battleSize < MusicParameters.LargeBattleTreshold)
      {
        if ((double) num1 < (double) MusicParameters.LargeBattleDistanceTreshold * (double) MusicParameters.LargeBattleDistanceTreshold)
          flag2 = true;
      }
      else if ((double) num1 < (double) MusicParameters.MaxBattleDistanceTreshold * (double) MusicParameters.MaxBattleDistanceTreshold)
        flag2 = true;
      if (!flag2)
        return;
      float startIntensity = (float) ((double) MusicParameters.DefaultStartIntensity + (double) ((float) battleSize / 1000f) * (double) MusicParameters.BattleSizeEffectOnStartIntensity + ((double) MBRandom.RandomFloat - 0.5) * ((double) MusicParameters.RandomEffectMultiplierOnStartIntensity * 2.0));
      MBMusicManager.Current.StartTheme(this._isSiegeBattle ? MBMusicManager.Current.GetSiegeTheme(this.Mission.MusicCulture.GetCultureCode()) : MBMusicManager.Current.GetBattleTheme(this.Mission.MusicCulture.GetCultureCode(), battleSize, out this._isPaganBattle), startIntensity);
      this._battleState = MusicBattleMissionView.BattleState.Started;
    }

    private void CheckForEnding()
    {
      if (!Mission.Current.IsMissionEnding)
        return;
      if (Mission.Current.MissionResult != null)
      {
        MBMusicManager.Current.StartTheme(MBMusicManager.Current.GetBattleEndTheme(this.Mission.MusicCulture.GetCultureCode(), Mission.Current.MissionResult.PlayerVictory), PsaiCore.Instance.GetPsaiInfo().currentIntensity, true);
        this._battleState = MusicBattleMissionView.BattleState.Ending;
      }
      else
      {
        MBMusicManager.Current.StartTheme(MusicTheme.BattleDefeat, PsaiCore.Instance.GetPsaiInfo().currentIntensity, true);
        this._battleState = MusicBattleMissionView.BattleState.Ending;
      }
    }

    void IMusicHandler.OnUpdated(float dt)
    {
      if (this._battleState == MusicBattleMissionView.BattleState.Starting)
      {
        if (this.Mission.MusicCulture == null && Mission.Current.GetMissionBehavior<DeploymentHandler>() == null && this._missionAgentSpawnLogic.IsDeploymentOver)
        {
          KeyValuePair<BasicCultureObject, int> keyValuePair = new KeyValuePair<BasicCultureObject, int>((BasicCultureObject) null, -1);
          Dictionary<BasicCultureObject, int> dictionary = new Dictionary<BasicCultureObject, int>();
          foreach (Team team in (List<Team>) this.Mission.Teams)
          {
            foreach (Agent activeAgent in (List<Agent>) team.ActiveAgents)
            {
              BasicCultureObject culture = activeAgent.Character.Culture;
              if (culture != null && culture.IsMainCulture)
              {
                if (!dictionary.ContainsKey(activeAgent.Character.Culture))
                  dictionary.Add(activeAgent.Character.Culture, 0);
                dictionary[activeAgent.Character.Culture]++;
                if (dictionary[activeAgent.Character.Culture] > keyValuePair.Value)
                  keyValuePair = new KeyValuePair<BasicCultureObject, int>(activeAgent.Character.Culture, dictionary[activeAgent.Character.Culture]);
              }
            }
          }
          if (keyValuePair.Key != null)
            this.Mission.MusicCulture = keyValuePair.Key;
          else
            this.Mission.MusicCulture = Game.Current.PlayerTroop.Culture;
        }
        if (this.Mission.MusicCulture != null)
          this.CheckForStarting();
      }
      if (this._battleState == MusicBattleMissionView.BattleState.Started || this._battleState == MusicBattleMissionView.BattleState.TurnedOneSide)
        this.CheckForEnding();
      this.CheckIntensityFall();
    }

    private enum BattleState
    {
      Starting,
      Started,
      TurnedOneSide,
      Ending,
    }
  }
}
